package org.scratchcrew.web.jsf;

import java.io.IOException;
import java.util.Locale;

import javax.faces.FacesException;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;

import org.apache.myfaces.application.DefaultViewHandlerSupport;
import org.apache.myfaces.application.ViewHandlerSupport;
import org.apache.myfaces.application.jsp.JspViewHandlerImpl;
import org.scratchcrew.web.jsf.myfaces.CustomViewHandlerSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Decorator of ViewHandler. It warps the original view handler and delegates to
 * its methods. If this is a {@link JspViewHandlerImpl} this wrapper sets
 * different {@link ViewHandlerSupport} implementation and it is
 * {@link CustomViewHandlerSupport}.
 * 
 */
public class CustomViewHandler extends ViewHandler {
	public static final String DEFAULT_VIEW_PREFIX_PARAM_NAME = "org.scratchcrew.web.jsf.DEFAULT_VIEW_PREFIX";
	public static final String DEFAULT_VIEW_PREFIX = "/WEB-INF/view";
	protected final Logger logger = LoggerFactory.getLogger(getClass());
	private ViewHandler originalViewHandler = null;

	/**
	 * Instantiates custom view handler. If the original view handler is myfaces
	 * {@link JspViewHandlerImpl} sets {@link CustomViewHandlerSupport} in place
	 * of the {@link DefaultViewHandlerSupport}.
	 * 
	 * @param handler
	 *            original view handler
	 */
	public CustomViewHandler(ViewHandler handler) {
		super();
		this.originalViewHandler = handler;
		if (handler instanceof JspViewHandlerImpl) {
			JspViewHandlerImpl jspViewHandler = (JspViewHandlerImpl) handler;
			DefaultViewHandlerSupport defaultViewHandlerSupport = new DefaultViewHandlerSupport();
			ViewHandlerSupport viewHandlerSupport = new CustomViewHandlerSupport(
					defaultViewHandlerSupport);
			if (logger.isTraceEnabled()) {
				logger.trace("Setting decorated view handler support"
						+ " for jsp view handler.");
			}
			jspViewHandler.setViewHandlerSupport(viewHandlerSupport);
		} else {
			logger.error("Unknown view handler implementation: "
					+ handler.getClass());
		}
	}

	/**
	 * Delegates to wrapped view handler.
	 */
	@Override
	public void renderView(FacesContext context, UIViewRoot view)
			throws IOException, FacesException {
		originalViewHandler.renderView(context, view);
	}

	/**
	 * Delegates to wrapped view handler.
	 */
	@Override
	public Locale calculateLocale(FacesContext context) {
		return originalViewHandler.calculateLocale(context);
	}

	/**
	 * Delegates to wrapped view handler.
	 */
	@Override
	public String calculateRenderKitId(FacesContext context) {
		return originalViewHandler.calculateRenderKitId(context);
	}

	/**
	 * Delegates to wrapped view handler.
	 */
	@Override
	public UIViewRoot createView(FacesContext context, String viewId) {
		return originalViewHandler.createView(context, viewId);
	}

	/**
	 * Delegates to wrapped view handler.
	 */
	@Override
	public String getActionURL(FacesContext context, String viewId) {
		return originalViewHandler.getActionURL(context, viewId);
	}

	/**
	 * Delegates to wrapped view handler.
	 */
	@Override
	public String getResourceURL(FacesContext context, String path) {
		return originalViewHandler.getResourceURL(context, path);
	}

	/**
	 * Delegates to wrapped view handler.
	 */
	@Override
	public UIViewRoot restoreView(FacesContext context, String viewId) {
		return originalViewHandler.restoreView(context, viewId);
	}

	/**
	 * Delegates to wrapped view handler.
	 */
	@Override
	public void writeState(FacesContext context) throws IOException {
		originalViewHandler.writeState(context);
	}

}
